package com.tools.common.object.string;


import com.tools.common.container.r.OnlyReadHashSet;
import com.tools.common.object.Note;

import java.util.Locale;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Pattern;

/**
 * 字符串操作的工具类
 * */
@Note("字符串操作的工具类")
public final class StrKit extends StringKit {

    private StrKit() {}

    @Note("打印输出格式的上边界的半边。常用于格式：[【半边】输出内容的标题【半边】]的输出")
    public static final String LOG_PRINT_RADIUS_BORDER = addString("==", 50);

    @Note("打印输出时，作为其内容的上下边框")
    public static final String LOG_PRINT_BORDER = LOG_PRINT_RADIUS_BORDER + LOG_PRINT_RADIUS_BORDER;



    /* ************************************************************************************************************
     *
     *
     *          其他操作
     *
     * ************************************************************************************************************
     * */



    /**
     * @param str 目标字符串
     * @return 去除字符串两边的空格、空白字符
     * */
    @Note("去除字符串两边的空格、空白字符")
    public static String trim(String str) {
        return (str == null) ? "" : str.trim();
    }


    /**
     * @param str 目标字符串
     * @return 去除字符串左边的空格、空白字符
     * */
    @Note("去除字符串左边的空格、空白字符")
    public static String trimLeft(String str) {
        if(str == null || str.isEmpty()) return "";
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if(!Character.isWhitespace(c)) {
                return str.substring(i);
            }
        }
        return "";
    }

    /**
     * @param str 目标字符串
     * @return 去除字符串右边的空格、空白字符
     * */
    @Note("去除字符串右边的空格、空白字符")
    public static String trimRight(String str) {
        if(str == null || str.isEmpty()) return "";
        for (int i = str.length() - 1; i >= 0; i--) {
            char c = str.charAt(i);
            if(!Character.isWhitespace(c)) {
                return str.substring(0, i + 1);
            }
        }
        return "";
    }


    /**
     * @param str 目标字符串
     * @return 去除字符串所有的空格、空白字符
     * */
    @Note("去除字符串所有的空格、空白字符")
    public static String removeWhites(String str) {
        if (str == null || str.isEmpty()) return str;
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if(Character.isWhitespace(c)) continue;
            builder.append(c);
        }
        return builder.toString();
    }


    /**
     * @param str 目标字符串
     * @param oldStr 旧的子串
     * @param newStr 新的子串
     * @return 把 str 中的 oldStr 子串替换为 newStr 子串
     * */
    @Note("把 str 中的 oldStr 子串替换为 newStr 子串")
    public static String replace(String str, String oldStr, String newStr) {
        if(str == null) {
            return "";
        }
        if(oldStr == null || newStr == null){
            return str;
        }
        return str.replace(oldStr, newStr);
    }


    @Note("字符串 str 按 ch 切分为字符串数组返回")
    public static String[] split(String str, String separator) {
        if(str == null || str.isEmpty()) return new String[0];
        if(separator == null || separator.isEmpty()) return str.split("");
        separator = Pattern.quote(separator);
        return str.split(separator);
    }

    @Note("字符串 str 按 , 逗号切分为字符串数组返回")
    public static String[] splitByComma(String str) {
        if(str == null || str.isEmpty()) return new String[0];
        if(!str.contains(",")) return new String[] {str};
        return str.split(",");
    }

    @Note("字符串 str 按 ; 分号切分为字符串数组返回")
    public static String[] splitBySemicolon(String str) {
        if(str == null || str.isEmpty()) return new String[0];
        if(!str.contains(",")) return new String[] {str};
        return str.split(";");
    }


    @Note("过滤字符串中出现的正则表达式的特殊符号，将其作为字面量输出")
    public static String filterRegexpChar(String str) {
        if(str == null || str.isEmpty()) return "";
        return Pattern.quote(str);
    }


    @Note("对引号/正则特殊字符等等做转义")
    public static String escapeSpecialChar(String str) {
        if(str == null || str.isEmpty()) return "";
        StringBuilder sb  = new StringBuilder();
        OnlyReadHashSet<Character> regexCharSet = getRegexCharSet();
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if(regexCharSet.contains(c)) {
                sb.append("\\");
            }
            sb.append(c);
        }
        return sb.toString();
    }


    /**
     * @param  str 要截取的目标字符串
     * @param start 从下标为几的字符开始截取
     * @param end 截取为下标为几的字符结束
     * @return 从 str 字符串下标为 start 的字符开始（包括它），截取到下标为 end 的位置结束（不包括它），把截取后的新字符串返回
     * */
    @Note("从 str 字符串下标为 start 的字符开始（包括它），截取到下标为 end 的位置结束（不包括它），把截取后的新字符串返回")
    public static String substring(String str, int start, int end) {
        if (str == null) return "";
        int length = str.length();
        if (end < 0) {
            end += length;
        }
        if (start < 0) {
            start += length;
        }
        if (end > length) {
            end = length;
        }
        if (start > end) {
            return "";
        }
        if (start < 0) {
            start = 0;
        }
        if (end < 0) {
            end = 0;
        }
        return str.substring(start, end);
    }

    /**
     * @param  str 要截取的目标字符串
     * @param start 从下标为几的字符开始截取
     * @return 从 str 字符串下标为 start 的字符开始（包括它），截取到字符串末尾，把截取后的新字符串返回
     * */
    @Note("从 str 字符串下标为 start 的字符开始（包括它），截取到字符串末尾，把截取后的新字符串返回")
    public static String substring(String str, int start) {
        if (str == null) return "";
        int length = str.length();
        if (start < 0) {
            start += length;
        }
        if (start < 0) {
            start = 0;
        }
        return start > length ? "" : str.substring(start);
    }


    /**
     * @param str 目标字符串
     * @param childStr 目标字符串中的子串
     * @return 在 str 中找到 childStr 第一次出现的位置，然后返回从这个位置裁剪到末尾的子串
     * */
    @Note("在 str 中找到 childStr 第一次出现的位置，然后返回从这个位置裁剪到末尾的子串")
    public static String substringFirst(String str, String childStr) {
        if(str == null || str.isEmpty()) return "";
        if(childStr == null || childStr.isEmpty()) return str;
        int first = str.indexOf(childStr);
        if(first == -1) return str;
        return str.substring(first);
    }


    /**
     * @param str 目标字符串
     * @param childStr 目标字符串中的子串
     * @return 在 str 中找到 childStr 最后一次出现的位置，然后返回从头裁剪到这个位置的子串
     * */
    @Note("在 str 中找到 childStr 最后一次出现的位置，然后返回从头裁剪到这个位置的子串")
    public static String substringLast(String str, String childStr) {
        if(str == null || str.isEmpty()) return "";
        if(childStr == null || childStr.isEmpty()) return str;
        int last = str.lastIndexOf(childStr);
        if(last == -1) return str;
        return str.substring(0, last);
    }



    /**
     * @param dbField 数据库字段名，一般是有下划线的
     * @return 将数据库字段名转为 JavaBean 对象的标准属性写法
     * */
    @Note("将数据库字段名转为 JavaBean 对象的标准属性写法")
    public static String toProperty(String dbField) {
        if(dbField == null || dbField.isEmpty()) {
            return "";
        }
        if(dbField.contains("_")) {
            dbField = dbField.toLowerCase(Locale.ROOT);
        }
        StringBuilder sb = new StringBuilder();
        int dbFieldLength = dbField.length();
        for(int i = 0 ; i <  dbFieldLength; i++) {
            char c = dbField.charAt(i);
            if(c != '_') {
                sb.append(c);
                continue;
            }
            int j = i + 1;
            if(j < dbFieldLength) {
                String ch = dbField.charAt(j) + "";
                sb.append(ch.toUpperCase(Locale.ROOT));
                i++;
            }
        }
        return sb.toString();
    }


    /**
     * @param property Java 对象的属性名称
     * @return 把小驼峰命名的属性名称转为标准数据库字段名称，如：【userId】 -> 【user_id】
     * */
    @Note("把小驼峰命名的属性名称转为标准数据库字段名称，如：【userId】 -> 【user_id】")
    public static String toDBField(String property) {
        if(property == null || property.isEmpty()) {
            return "";
        }
        if(VerifyKit.isLowercase(property)) {
            return property;
        }
        StringBuilder sb = new StringBuilder();
        for(int i = 0 ; i < property.length() ; i++) {
            char c = property.charAt(i);
            if(c >= 65 && c <= 90) {
                String upperCase = ("" + c).toLowerCase(Locale.ROOT);
                sb.append("_").append(upperCase);
                continue;
            }
            sb.append(c);
        }
        return sb.toString();
    }


    /**
     * @param template 字符串模板
     * @param count 新增多少个这样的模板
     * @return 把 count 个 template 字符串拼接起来返回
     * */
    @Note("把 count 个 template 字符串拼接起来返回")
    public static String addString(String template, int count) {
        if(template == null || template.isEmpty() || count <= 0) return "";
        StringBuilder s = new StringBuilder();
        for(int i = 0 ; i < count ; i++){
            s.append(template);
        }
        return s.toString();
    }


    /**
     * @param str 源字符串
     * @param separator 源字符串中的分隔符子串
     * @return 根据子串分割源字符串，将分割的部分用正则表达式的 | 连接，用于正则匹配查询
     * */
    @Note("根据子串分割源字符串，将分割的部分用正则表达式的 | 连接，用于正则匹配查询")
    public static String regOr(String str, String separator) {
        if(str == null || str.isEmpty()) return "";
        StringBuilder builder = new StringBuilder().append('(');
        int index = 0;
        if(separator == null || separator.isEmpty()) {
            for (int i = 0; i < str.length(); i++) {
                builder.append(str.charAt(i)).append('|');
            }
            return builder.substring(0, builder.length() - 1) + ')';
        }
        index = str.indexOf(separator, index);
        if(index == -1) {
            return builder.append(str).append(')').toString();
        }
        builder.append(str, 0, index).append('|');
        int off = separator.length();
        index += off;
        int j;
        while ((j = str.indexOf(separator, index)) != -1) {
            String s = str.substring(index, j);
            builder.append(s).append('|');
            index = j + off;
        }
        return builder.append(str.substring(index)).append(')').toString();
    }



    @Note("克隆并返回一个新的中文汉字数组的长度")
    public static char[] cloneChineseCharArray() {
        return default_getChineseCharArray().clone();
    }

    @Note("获取中文汉字数组的长度")
    public static int chineseCharArrayLength() {
        return default_getChineseCharArray().length;
    }

    @Note("获取指定索引位置的一个汉字，如果索引不合法则返回空字符")
    public static char getChineseChar(int index) {
        char[] chars = default_getChineseCharArray();
        if(index < 0 || index >= chars.length) return '\u0000';
        return chars[index];
    }

    @Note("随机返回一个汉字")
    public static char randomChineseChar() {
        char[] chars = default_getChineseCharArray();
        int index = ThreadLocalRandom.current().nextInt(chars.length);
        return chars[index];
    }


    @Note("生成一个随机中文汉字组成的字符串")
    public static String newChineseWord(int length) {
        return newChineseWord(length, null);
    }

    @Note("生成一个随机中文汉字组成的字符串，每个汉字之间用 separator 子串分隔")
    public static String newChineseWord(int length, String separator) {
        if(length <= 0) return "";
        char[] chars = default_getChineseCharArray();
        int charsLength = chars.length;
        StringBuilder builder = new StringBuilder();
        ThreadLocalRandom random = ThreadLocalRandom.current();
        if(separator == null || separator.isEmpty()) {
            for(int i = 0; i < length; i++) {
                int index = random.nextInt(charsLength);
                builder.append(chars[index]);
            }
            return builder.toString();
        }
        for(int i = 0; i < length; i++) {
            int index = random.nextInt(charsLength);
            builder.append(separator).append(chars[index]);
        }
        int separatorLength = separator.length();
        return builder.substring(separatorLength);
    }

}
